package com.contract.management.web;

import java.io.File;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.transaction.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;
import com.contract.management.bean.CompanyInfo;
import com.contract.management.bean.ReturnMessage;
import com.contract.management.domain.CommJpaRepository;
import com.contract.management.domain.Config;
import com.contract.management.domain.ContFile;
import com.contract.management.domain.ContSmallClass;
import com.contract.management.domain.Contract;
import com.contract.management.domain.User;
import com.contract.management.domain.WorkflowLog;
import com.contract.management.domain.WorkflowNode;
import com.contract.management.service.ContractService;
import com.contract.management.util.ContractUtils;
import com.contract.management.util.PdfUtils;
import com.contract.management.util.StrUtils;
import com.contract.management.util.WorkFlowUtils;

@Controller
@RequestMapping("/apply")
public class ApplyController {

	@Value("${office.basepath}")
	private String basePath;
	
	private String separator = System.getProperty("file.separator");
	
	@Autowired
	private CommJpaRepository repo;
	
	@Autowired
	private ContractService service;
	
	//申请空白合同（选择合同模板）
	@RequestMapping("/blank")
	public String applyBlank(Model model) {
		Contract ct = new Contract();
		ct.setYcfq("O");
		ct.setIsHjb(true);
		ct.setHasFjtk(false);

		model.addAttribute("ct", ct);
		model.addAttribute("companys", repo.query("from Config where type = 'COMPANY' order by sort"));
		model.addAttribute("areas", repo.query("from Config where type = 'AREA' order by sort"));
		model.addAttribute("ywlxs", repo.query("from Config where type = 'YWLX' order by sort"));		
		model.addAttribute("bigClasses", repo.query("select id, name from ContBigClass where area = 'A'"));
		model.addAttribute("smallClasses", repo.query("select CONCAT(id, '_', hasYcfq, '_', hasHjb) as id, name from ContSmallClass where bigClass.id = 1"));
		return "apply_blank";
	}
	//申请空白合同（提交）
	@RequestMapping("/blank/two")
	public String applyBlankTwo(HttpServletRequest req, HttpSession session, Model model, Contract ct) {
		String refUrl = req.getHeader("Referer");
		if(refUrl == null || !refUrl.endsWith("/apply/blank")) {
			return "redirect:/apply/blank";
		}
		
		//模板选择信息
		setConfig(ct);
		//设置默认值
		CompanyInfo info = JSON.parseObject(repo.queryOne("select name from Config where type='INFO' and code = ?0", ct.getArea() + ct.getCompany().getCode()), CompanyInfo.class);
		info.copyToContract(ct);
		
		User user = (User)session.getAttribute("user");
		ct.setUser(user);
		//保存合同
		service.insertBlankContract(ct);
		
		model.addAttribute("ct", ct);
		return "apply_blank_two";
	}

	//申请电子合同（1. 选择合同模板）
	@RequestMapping("/elec/one")
	public String applyElecOne(Model model) {
		Contract ct = new Contract();
		ct.setYcfq("O");
		ct.setIsHjb(false);
		ct.setHasFjtk(false);

		model.addAttribute("ct", ct);
		model.addAttribute("companys", repo.query("from Config where type = 'COMPANY' order by sort"));
		model.addAttribute("areas", repo.query("from Config where type = 'AREA' order by sort"));
		model.addAttribute("ywlxs", repo.query("from Config where type = 'YWLX' order by sort"));
		
		model.addAttribute("bigClasses", repo.query("select id, name from ContBigClass where area = 'A'"));
		model.addAttribute("smallClasses", repo.query("select CONCAT(id, '_', hasYcfq, '_', hasHjb), name from ContSmallClass where bigClass.id = 1"));
		return "apply_elec_one";
	}

	//申请电子合同（2. 填写合同内容）
	@RequestMapping("/elec/two")
	public String applyElecTwo(HttpServletRequest req, HttpSession session, Model model, Contract ct) {
		String refUrl = req.getHeader("Referer");
		if(refUrl == null || !refUrl.endsWith("/apply/elec/one")) {
			return "redirect:/apply/elec/one";
		}
		//模板选择信息
		setConfig(ct);
		
		if("DS".equals(ct.getYwlx())) {
			ct.setSbItems(service.createDsItems());
		}
		//设置默认值
		CompanyInfo info = JSON.parseObject(repo.queryOne("select name from Config where type='INFO' and code = ?0", ct.getArea() + ct.getCompany().getCode()), CompanyInfo.class);
		info.copyToContract(ct);
		
		//正常报价
		List<Object[]> zcbjs = repo.query("select bjje, concat('[', bjje, ']', smallType) from Bjd where ywlx = ?0", ct.getYwlx());
		if(zcbjs.size() == 0) {
			zcbjs.add(new Object[]{0, "无报价信息"});
		}
		ct.setFkfs(1);
		
		model.addAttribute("temp_info", ContractUtils.getSeleTemp(ct));
		model.addAttribute("temp_id", service.getTemplateId(ct));
		model.addAttribute("contract", ct);
		model.addAttribute("zcbjs", zcbjs);
		model.addAttribute("form_action", "apply/elec/three");
		return "apply_elec_two";
	}

	//申请电子合同（3. 完成）
	@RequestMapping("/elec/three")
	public String applyElecThree(HttpServletRequest req, HttpSession session, Contract ct, Model model) {
		String refUrl = req.getHeader("Referer");
		if(refUrl == null || !refUrl.endsWith("/apply/elec/two")) {
			return "redirect:/apply/elec/one";
		}		
		ct.setExtraData(JSON.toJSONString(ct.getData()));
		setConfig(ct);
		//设置默认值
		CompanyInfo info = JSON.parseObject(repo.queryOne("select name from Config where type='INFO' and code = ?0", ct.getArea() + ct.getCompany().getCode()), CompanyInfo.class);
		ct.setAccount(info.getAccount());
		ct.setBank(info.getBank());
		ct.setBankNumber(info.getBankNumber());
		
		User user = (User)session.getAttribute("user");
		ct.setUser(user);
		//保存合同
		WorkflowNode nextNode = service.insertContract(ct);

		model.addAttribute("ct", ct);
		model.addAttribute("message", nextNode.getDesc());
		return "apply_elec_three";
	}

	//选择联系人
	@RequestMapping("/lxr/list")
	@ResponseBody
	public List<Object[]> lxrList() {
		return repo.query("select u.id, d.deptName, u.name, u.post, u.telephone, u.email from User u left join u.dept d");
	}
	
	//获得申请、修改、打印、上传的合同数量
	@RequestMapping("/count")
	@ResponseBody
	public ReturnMessage count(HttpSession session) {
		User user = (User)session.getAttribute("user");
		Long apply = repo.queryOne("select count(*) from Contract c where c.user = ?0 and c.curNode.id = 1", user);
		Long modify = repo.queryOne("select count(*) from Contract c where c.user = ?0 and c.curNode.id = 2", user);
		Long print = repo.queryOne("select count(*) from Contract c where c.user = ?0 and c.curNode.id = 6", user);
		Long put = repo.queryOne("select count(*) from Contract c where c.user = ?0 and (c.curNode.id = 8 or c.curNode.id = 16)", user);
		Map<String, String> map = new HashMap<String, String>() {{
			put("apply", apply == 0 ? "" : String.valueOf(apply));
			put("modify", modify == 0 ? "" : String.valueOf(modify));
			put("print", print == 0 ? "" : String.valueOf(print));
			put("put", put == 0 ? "" : String.valueOf(put));
		}};
		return new ReturnMessage(true, map);
	}

	//合同申请列表（填写完合同未提交）
	@RequestMapping("/apply/list")
	public String applyList(Model model, HttpSession session) {
		User user = (User)session.getAttribute("user");
		List<Map<String, Object>> data = service.getContList(user, null, 1);
		for (Map<String, Object> map : data) {
			StringBuilder option = new StringBuilder();
			if(!((int)map.get("curNodeId") == 1 && (int)map.get("type") == 2)) {
				option.append("<a href = 'javascript:;' onclick='edit_cont(").append(map.get("id")).append(")'>修改</a>").append("&nbsp;&nbsp;");
			}
			option.append("<a href = 'javascript:;' onclick='apply_audit(").append(map.get("id")).append(")'>").
				append("申请").append(map.get("nextOper")).append("</a>");
			map.put("option", option.toString());
		}
		
		model.addAttribute("rows", data);
		model.addAttribute("url", "apply/apply/list");
		model.addAttribute("title", "申请提交");
		return "apply_list";
	}
	
	//获得可用审批人
	@RequestMapping("/apply")
	@ResponseBody
	public ReturnMessage apply(HttpSession session, int id) {
		Contract ct = repo.find(Contract.class, id);
		User user = (User)session.getAttribute("user");
		
		if(ct == null) {
			return new ReturnMessage(false, "该合同不存在");
		}
		if(user.getId() != (int)ct.getUser().getId()) {
			return new ReturnMessage(false, "您没有该合同申请权限");
		}
		int nodeId = ct.getCurNode().getId();
		if(nodeId != 1 && nodeId != 2 && nodeId != 6 && nodeId != 8 && nodeId != 16) {
			return new ReturnMessage(false, "该合同申请操作错误");
		}

		WorkflowNode nextNode = WorkFlowUtils.getNextNode(ct, repo);
		
		List<Map<String, Object>> files = repo.query("select new map(f.id as id, f.filename as filename, f.oraName as oraName, f.size as size, f.type as type) from ContFile f where f.cont.id = ?0", ct.getId());
		nextNode.setFiles(files);
		
		if(nextNode.getDesc() == null) nextNode.setDesc("申请" + nextNode.getName());
		Map<String, Object> msg = new HashMap<>();
		msg.put("nextNode", nextNode);
		msg.put("ht", ct.getContSmallClass().getHt());
		msg.put("zl", ct.getContSmallClass().getZl());
		return new ReturnMessage(true, msg);
	}
	
	/**
	 * 业务申请提交
	 * 
	 * @param session
	 * @param id	合同ID
	 * @param oper	操作人（为空提交给自己）
	 * @return
	 */
	@RequestMapping("/apply/submit")
	@ResponseBody
	@Transactional
	public ReturnMessage applySubmit(HttpSession session, int id, Integer oper, String auditMemo, String act) {
		User user = (User)session.getAttribute("user");
		Contract ct = repo.find(Contract.class, id);
		User audit = oper == null ? user : new User(oper);
		WorkflowNode nextNode = null;
		
		if("cancel".equals(act)) {
			nextNode = repo.find(WorkflowNode.class, 18);
		} else if("apply".equals(act)) {
			nextNode = WorkFlowUtils.getNextNode(ct, repo);
		}
		
		ct.setAuditMemo(auditMemo);
		ct.setCurNode(nextNode);
		ct.setNodeInfo(nextNode.getName());
		ct.setNextOper(nextNode.getName());
		ct.setAudit(audit);
		repo.merge(ct);
		
		WorkflowLog log = new WorkflowLog();
		log.setCt(ct);
		log.setUser(user);
		log.setSpjg(1);
		log.setSpsm("申请" + nextNode.getName());
//		log.setMemo(nextNode.getDesc());
		log.setCreateTime(new Date());
		repo.persist(log);

		return new ReturnMessage(true);
	}

	//合同打印列表
	@RequestMapping("/print/list")
	public String printList(Model model, HttpSession session) {
		User user = (User)session.getAttribute("user");
		List<Map<String, Object>> data = service.getContList(user, null, 6);
		for (Map<String, Object> map : data) {
			StringBuilder option = new StringBuilder("<a href = 'javascript:;' onclick='print_cont(").
					append(map.get("id")).append(")'>打印</a>").append("&nbsp;&nbsp;").
					append("<a href = 'javascript:;' onclick='apply_audit(").append(map.get("id")).append(")'>").
					append("申请盖章").append("</a>");
			map.put("option", option.toString());
		}
		
		model.addAttribute("rows", data);
		model.addAttribute("url", "apply/print/list");
		model.addAttribute("title", "合同打印");
		return "apply_list";
	}
	
	//合同修改列表
	@RequestMapping("/modify/list")
	public String modifyList(Model model, HttpSession session) {
		User user = (User)session.getAttribute("user");
		List<Map<String, Object>> data = service.getContList(user, null, 2);
		for (Map<String, Object> map : data) {
			StringBuilder option = new StringBuilder("<a href = 'javascript:;' onclick='edit_cont(").append(map.get("id")).append(")'>修改</a>");
			option.append("  <a href = 'javascript:;' onclick='edit_fjtk(").append(map.get("id")).append(")'>修改附加条款</a>");
			map.put("option", option.toString());
		}
		model.addAttribute("rows", data);
		model.addAttribute("url", "apply/modify/list");
		model.addAttribute("title", "合同修改");
		return "apply_list";
	}
	
	//合同修改附加条款
	@ResponseBody
	@RequestMapping("/modify/fjtk")
	public Object[]  modifyFjtk(int id, HttpSession session) {
		List<Object[]> list = repo.query("select fjtkAdd, fjtkDel from Contract where id = ?0", id);
		return list.get(0);
	}
	
	@ResponseBody
	@Transactional
	@RequestMapping("/modify/fjtk/save")
	public ReturnMessage  modifyFjtk(int id, String fjtkAdd, String fjtkDel) {
		repo.queryUpdate("update Contract set hasFjtk = ?0, fjtkAdd = ?1, fjtkDel = ?2 where id = ?3", true, fjtkAdd, fjtkDel, id);
		return new ReturnMessage(true);
	}
	
	//合同上传列表
	@RequestMapping("/put/list")
	public String putList(Model model, HttpSession session) {
		User user = (User)session.getAttribute("user");
		List<Map<String, Object>> data = service.getContList(user, null, 8, 16);
		for (Map<String, Object> map : data) {
			StringBuilder option = new StringBuilder();
			if((int)map.get("type") == 2) {
				option.append("<a href='/contract/edit/" + map.get("id") + "'>录入</a>&nbsp;");
			}
			option.append("<a href = 'javascript:;' onclick='put_cont(").
					append(map.get("id")).append(")'>上传资料</a>");
			option.append("&nbsp;&nbsp;<a href = 'javascript:;' onclick='cancel_audit(").
					append(map.get("id")).append(")'>作废</a>");
			map.put("option", option.toString());
		}
		model.addAttribute("rows", data);
		model.addAttribute("url", "apply/put/list");
		model.addAttribute("title", "合同资料上传");
		return "apply_list";
	}
	
	/**
	 * 合同上传提交
	 * @param session
	 * @param id
	 * @param oper
	 * @param docs
	 * @return
	 */
	@RequestMapping(value = "/put/submit", method = RequestMethod.POST)
	@ResponseBody
	@Transactional
	public ReturnMessage putSubmit(HttpSession session, int id, int oper, String docs) {
		
		User user = (User)session.getAttribute("user");
		Contract ct = repo.find(Contract.class, id);
		if(ct == null) {
			return new ReturnMessage(false, "无此合同");
		}
		if((int)ct.getUser().getId() != (int)user.getId()) {
			return new ReturnMessage(false, "您没有上传该合同资料权限");
		}
		if(ct.getCurNode().getId() != 8 && ct.getCurNode().getId() != 16) {
			return new ReturnMessage(false, "该操作无效");
		}
		List<ContFile> files = JSON.parseArray(docs, ContFile.class);
		
		//删除已经删除的图片
		List<Integer> list = files.stream().
				filter(file -> file.getId() != null).
				map(file -> file.getId()).
				collect(Collectors.toList());
		List<String> delFiles = null;
		if(list.size() == 0) {
			delFiles = repo.query("select filename from ContFile f where f.cont.id = ?0", id);
		} else {
			delFiles = repo.query("select filename from ContFile f where f.cont.id = ?0 and f.id not in (?1)", id, list);
		}
		
		for (String file : delFiles) {
			File f = new File(basePath + "uploads", file);
			f.delete();
		}
		
		repo.queryUpdate("delete from ContFile f where f.cont.id = ?0", id);
		
		for (ContFile contFile : files) {
			contFile.setCont(ct);
			if(contFile.getId() == null) {
				File f = new File(basePath + "temp", contFile.getFilename());
				File newFile = new File(basePath + "uploads", contFile.getFilename()); 
				if(f.renameTo(newFile)) {
					//pdf 转图片
					if(contFile.getFilename().toLowerCase().endsWith("pdf")) {
						String filename = PdfUtils.toPic(newFile);
						if(filename != null) contFile.setFilename(filename);
					}
					repo.persist(contFile);
				}
			} else {
				contFile.setId(null);
				repo.persist(contFile);
			}
		}

		WorkflowNode nextNode = WorkFlowUtils.getNextNode(ct, repo);
		ct.setCurNode(nextNode);
		ct.setNodeInfo(nextNode.getName());
		ct.setNextOper("");
		ct.setAudit(new User(oper));
		repo.merge(ct);
		
		WorkflowLog log = new WorkflowLog();
		log.setCt(ct);
		log.setUser(user);
		log.setSpjg(1);
		log.setSpsm("合同资料上传完成，申请" + nextNode.getName());
//		log.setMemo(nextNode.getDesc());
		log.setCreateTime(new Date());
		repo.persist(log);

		return new ReturnMessage(true);
	}
		
	@RequestMapping("/put/delete")
	@ResponseBody
    public ReturnMessage delete(int key, String filename) {
		String filePath = basePath + separator + "pics" + separator;
		if(filename != null) {
			File f = new File(filePath, filename);
			f.delete();
		}
		return new ReturnMessage(true);
	}
	
	private void setConfig(Contract ct) {
		ContSmallClass smallClass = null;
		if(ct.getContSmallClass() == null) {
			String scid = ct.getSmallClass().split("_")[0];
			smallClass = repo.queryOne("from ContSmallClass where id = ?0", Integer.valueOf(scid));
			ct.setContSmallClass(smallClass);
		} else {
			smallClass = repo.queryOne("from ContSmallClass where id = ?0", ct.getContSmallClass().getId());
			ct.setContSmallClass(smallClass);
		}
		
		if(StrUtils.isEmpty(smallClass.getTempNo())) {
			throw new RuntimeException("该合同模板不存在，请联系系统管理员！");
		}
		ct.setCompany(repo.queryOne("from Config where id = ?0 and type='COMPANY'", ct.getCompany().getId()));
		ct.setYwlx(smallClass.getTempNo().split("_")[0]);
		
		if(smallClass.getHasYcfq() == 0) ct.setYcfq(smallClass.getDefaultYcfq());
		if(smallClass.getHasHjb() == 0) ct.setIsHjb(smallClass.getDefaultHjb() == 0 ? false : true);
	}
	
	//合同作废列表
	@RequestMapping("/delete/list")
	public String deleteList(Model model, HttpSession session) {
		User user = (User)session.getAttribute("user");
		List<Map<String, Object>> data = service.getContList(user, null, 1, 2, 3, 4, 5, 6, 7);
		for (Map<String, Object> map : data) {
			StringBuilder option = new StringBuilder();
			option.append("<a href = 'javascript:;' onclick='cancel_cont(").
					append(map.get("id")).append(")'>合同作废</a>");
			map.put("option", option.toString());
		}
		model.addAttribute("rows", data);
		model.addAttribute("url", "apply/delete/list");
		model.addAttribute("title", "合同作废");
		return "delete_list";
	}
	@RequestMapping("/delete")
	@Transactional
	@ResponseBody
	public ReturnMessage delete(Model model, HttpSession session, int id) {
		User user = (User)session.getAttribute("user");
		Contract ct = repo.find(Contract.class, id);
		if(ct == null) {
			return new ReturnMessage(false, "无此合同");
		}
		if((int)ct.getUser().getId() != (int)user.getId()) {
			return new ReturnMessage(false, "该操作无效");
		}
		if(ct.getCurNode().getId() > 7) {
			return new ReturnMessage(false, "该操作无效");
		}
		
		repo.queryUpdate("delete from WorkflowLog where ct = ?0", ct);
		repo.queryUpdate("delete from SbItems where ct = ?0", ct);
		repo.remove(ct);
		return new ReturnMessage(true);
	}
	
	//作废合同申请
	@RequestMapping("/cancel")
	@ResponseBody
	public ReturnMessage cancel(HttpSession session, int id) {
		Contract ct = repo.find(Contract.class, id);
		User user = (User)session.getAttribute("user");
		
		if(ct == null) {
			return new ReturnMessage(false, "该合同不存在");
		}
		if(user.getId() != (int)ct.getUser().getId()) {
			return new ReturnMessage(false, "您没有该合同申请权限");
		}
		int nodeId = ct.getCurNode().getId();
		
		WorkflowNode nextNode = new WorkflowNode();
		nextNode.setId(18);
		nextNode.setOpers(repo.query("select new User(id, name) from User u where u.dept.right.id = 3"));
		
		if(nextNode.getDesc() == null) nextNode.setDesc("申请作废合同");
		Map<String, Object> msg = new HashMap<>();
		msg.put("nextNode", nextNode);
		return new ReturnMessage(true, msg);
	}
	
	//合同资料补录列表
	@RequestMapping("/blzl/list")
	public String blzlList(Model model, HttpSession session) {
		User user = (User)session.getAttribute("user");
		List<Map<String, Object>> data = service.getContList(user, null, 13);
		for (Map<String, Object> map : data) {
			StringBuilder option = new StringBuilder();
			option.append("<a href = 'javascript:;' onclick='blzl_add(").append(map.get("id")).append(")'>").
				append("补录资料").append("</a>");
			option.append("&nbsp;&nbsp;<a href = 'javascript:;' onclick='cancel_audit(").
			append(map.get("id")).append(")'>作废</a>");
			map.put("option", option.toString());
		}
		
		model.addAttribute("rows", data);
		model.addAttribute("url", "apply/blzl/list");
		model.addAttribute("title", "补录资料");
		return "apply_list";
	}
	
	/**
	 * 合同上传提交
	 * @param session
	 * @param id
	 * @param oper
	 * @param docs
	 * @return
	 */
	@RequestMapping(value = "/blzl/submit", method = RequestMethod.POST)
	@ResponseBody
	@Transactional
	public ReturnMessage blzlSubmit(HttpSession session, int id, String docs) {
		
		User user = (User)session.getAttribute("user");
		Contract ct = repo.find(Contract.class, id);
		if(ct == null) {
			return new ReturnMessage(false, "无此合同");
		}
		if((int)ct.getUser().getId() != (int)user.getId()) {
			return new ReturnMessage(false, "您没有上传该合同资料权限");
		}
		if(ct.getCurNode().getId() != 13) {
			return new ReturnMessage(false, "该操作无效");
		}
		List<ContFile> files = JSON.parseArray(docs, ContFile.class);
		
		for (ContFile contFile : files) {
			contFile.setCont(ct);
			File f = new File(basePath + "temp", contFile.getFilename());
			File newFile = new File(basePath + "uploads", contFile.getFilename()); 
			if(f.renameTo(newFile)) {
				//pdf 转图片
				if(contFile.getFilename().toLowerCase().endsWith("pdf")) {
					String filename = PdfUtils.toPic(newFile);
					if(filename != null) contFile.setFilename(filename);
				}
				repo.persist(contFile);
			}
		}
		
		WorkflowLog log = new WorkflowLog();
		log.setCt(ct);
		log.setUser(user);
		log.setSpjg(1);
		log.setSpsm("补录合同资料");
		log.setCreateTime(new Date());
		repo.persist(log);
		
		return new ReturnMessage(true);
	}
}
